using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class UI_InGame : MonoBehaviour
{
    [Header("----- Health Bar -----")]
    [SerializeField] private Image _healthBarImage;
    [SerializeField] private TextMeshProUGUI _healthTMP;
    private float _currentHealthFillAmount;
    private float _targetHealthFillAmount;

    [Header("----- Exp Bar -----")]
    [SerializeField] private Image _expBarImage;
    [SerializeField] private TextMeshProUGUI _gradeTMP;
    [SerializeField] private float _interpolateSpeed = 8f; // 插值速度（越大越快）
    private float _currentExpFillAmount;
    private float _targetExpFillAmount;

    [Header("----- Wave Timer Info -----")]
    [SerializeField] private TextMeshProUGUI _waveCountTMP;
    [SerializeField] private TextMeshProUGUI _waveTimerTMP;
    [SerializeField] private TextMeshProUGUI _nextWaveTimeTMP;
    [SerializeField] private Color warnColor;
    private Color _originalTMPColor;
    private WaveData _currentWaveData;

    private void Awake()
    {
        _originalTMPColor = _waveTimerTMP.color;
        
        _waveTimerTMP.enabled = false;

        _nextWaveTimeTMP.enabled = false;
    }
    private void OnEnable()
    {
        //绑定更新UI健康条事件
        EventCenter.AddEventListener<float, float>(EventName.UI_UpdateHealthBar, UpdateHealthBar);
        //绑定更新UI经验条事件
        EventCenter.AddEventListener<float, float, int>(EventName.UI_UpdateExpBar, UpdateExpBar);

        EventCenter.AddEventListener<WaveData>(EventName.UI_UpdateWaveInfo, UpdateWaveInfo);

        EventCenter.AddEventListener(EventName.CurrentWaveFinish, WaveFinishTimer);
    }

    private void OnDisable()
    {
        //移除绑定更新UI健康条事件
        EventCenter.RemoveEventListener<float, float>(EventName.UI_UpdateHealthBar, UpdateHealthBar);
        //移除绑定更新UI经验条事件
        EventCenter.RemoveEventListener<float, float, int>(EventName.UI_UpdateExpBar, UpdateExpBar);

        EventCenter.RemoveEventListener<WaveData>(EventName.UI_UpdateWaveInfo, UpdateWaveInfo);

        EventCenter.RemoveEventListener(EventName.CurrentWaveFinish, WaveFinishTimer);
    }

    private void Start()
    {
        StartCoroutine(LerpUpdateExpBarCo());
        StartCoroutine(LerpUpdateHealthBarCo());
    }

    /// <summary>
    /// 更新当前波次UI
    /// </summary>
    /// <param name="currentWaveData"></param>
    private void UpdateWaveInfo(WaveData currentWaveData)
    {
        _waveCountTMP.text = currentWaveData.waveName;

        _currentWaveData = currentWaveData;

        StartCoroutine(WaveTimerCo(currentWaveData.waveDuration));
    }
    private IEnumerator WaveTimerCo(float waveDuration)
    {
        _waveTimerTMP.enabled = true;
        _waveCountTMP.enabled = true;
        float startWaveDuration = waveDuration;
        while (waveDuration > 0)
        {
            waveDuration -= Time.deltaTime;

            float displayTimer = Mathf.Clamp(Mathf.FloorToInt(waveDuration), 0, startWaveDuration);

            _waveTimerTMP.text = displayTimer.ToString();

            _waveTimerTMP.color = displayTimer > 5 ? _originalTMPColor : warnColor;

            yield return null;
        }
        _waveTimerTMP.text = "0";

        yield return new WaitForSeconds(_currentWaveData.waveOverDelay);
        
        _waveTimerTMP.enabled = false;
        _waveCountTMP.enabled = false;
    }

    /// <summary>
    /// 距离下一波敌人生成计时器
    /// </summary>
    private void WaveFinishTimer()
    {
        StartCoroutine(NextWaveTimerCo());
    }
    private IEnumerator NextWaveTimerCo()
    {
        _waveTimerTMP.enabled = false;

        _nextWaveTimeTMP.enabled = true;

        float time = _currentWaveData.nextWaveWaitInterval;

        while (time > 0)
        {
            time -= Time.deltaTime;

            float displayTime = Mathf.Clamp(Mathf.FloorToInt(time), 0, _currentWaveData.nextWaveWaitInterval);

            _nextWaveTimeTMP.text = $"距离下一波还有{displayTime}s";
            yield return null;
        }

        _nextWaveTimeTMP.enabled = false;
    }

    /// <summary>
    /// 更新健康条
    /// </summary>
    /// <param name="currentHealth"></param>
    /// <param name="maxHealth"></param>
    private void UpdateHealthBar(float currentHealth, float maxHealth)
    {
        _targetHealthFillAmount = currentHealth / maxHealth;

        _healthTMP.text = $"{Mathf.FloorToInt(currentHealth)} / {Mathf.FloorToInt(maxHealth)}";
    }

    /// <summary>
    /// 更新经验条
    /// </summary>
    /// <param name="currentGradeExp"></param>
    /// <param name="maxGradeExp"></param>
    private void UpdateExpBar(float currentGradeExp, float maxGradeExp, int grade)
    {
        _targetExpFillAmount = currentGradeExp / maxGradeExp;

        _gradeTMP.text = $"LV.{grade}";
    }
    /// <summary>
    /// 插值更新经验条
    /// </summary>
    /// <returns></returns>
    private IEnumerator LerpUpdateExpBarCo()
    {
        while (true)
        {
            if (_currentExpFillAmount > _targetExpFillAmount)
                yield return StartCoroutine(SmoothExpToFullFill());

            // 线性插值：每帧向目标值靠近
            _currentExpFillAmount = Mathf.Lerp(_currentExpFillAmount, _targetExpFillAmount, _interpolateSpeed * Time.deltaTime);

            // 处理精度：当接近目标值时直接吸附，避免微小误差
            if (Mathf.Abs(_currentExpFillAmount - _targetExpFillAmount) < 0.01f)
            {
                _currentExpFillAmount = _targetExpFillAmount;
            }

            _expBarImage.fillAmount = _currentExpFillAmount;

            yield return null;
        }
    }
    
    /// <summary>
    /// 玩家升级时的经验平滑过渡到满格
    /// </summary>
    /// <returns></returns>
    private IEnumerator SmoothExpToFullFill()
    {
        float targetFillAmount = 1f;
        while (Mathf.Abs(_currentExpFillAmount - targetFillAmount) > 0.02f)
        {
            _currentExpFillAmount = Mathf.Lerp(_currentExpFillAmount, targetFillAmount, _interpolateSpeed * 2 * Time.deltaTime);
            _expBarImage.fillAmount = _currentExpFillAmount;
            yield return null;
        }
        _expBarImage.fillAmount = targetFillAmount;
        _currentExpFillAmount = 0f; // 强制归零，消除精度误差
    }
    /// <summary>
    /// 插更新健康条
    /// </summary>
    /// <returns></returns>
    private IEnumerator LerpUpdateHealthBarCo()
    {
        while (true)
        {
            // 线性插值：每帧向目标值靠近
            _currentHealthFillAmount = Mathf.Lerp(_currentHealthFillAmount, _targetHealthFillAmount, _interpolateSpeed * Time.deltaTime);

            _healthBarImage.fillAmount = _currentHealthFillAmount;

            yield return null;
        }
    }
}
